package sample.batch.flow;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.job.flow.FlowExecutionStatus;
import org.springframework.batch.core.job.flow.JobExecutionDecider;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;

/**
 * @date 2020/8/17
 */
@SpringBootApplication
@EnableBatchProcessing
public class FlowApplication {

	private Logger LOGGER = LoggerFactory.getLogger(FlowApplication.class);

	public static void main(String[] args) throws Exception {
		System.exit(SpringApplication.exit(SpringApplication.run(FlowApplication.class, args)));
	}

	@Autowired
	public JobBuilderFactory jobBuilderFactory;

	@Autowired
	public StepBuilderFactory stepBuilderFactory;

	//@Bean
	public Job flowJob(@Qualifier("step1") Step step1,
			@Qualifier("step2") Step step2,
			@Qualifier("step3") Step step3,
			JobExecutionDecider decider) {
		return jobBuilderFactory.get("flowJob")
				.flow(step1)
				.next(decider).on("GO 2").to(step2)
				.from(decider).on("GO 3").to(step3)
				.end()
				.build();
	}

	@Bean
	public Job flowJob2(@Qualifier("step1") Step step1,
			@Qualifier("step2") Step step2,
			@Qualifier("step3") Step step3,
			JobExecutionDecider decider) {
		return jobBuilderFactory.get("onFailFlowJob")
				.flow(step1)
				.on("FAILED").stopAndRestart(step1)
				.from(step1).on("GO 3").to(step3)
				.end()
				.build();
	}

	@Bean
	public JobExecutionDecider decider() {
		return new JobExecutionDecider() {
			@Override
			public FlowExecutionStatus decide(JobExecution jobExecution, StepExecution stepExecution) {
				return new FlowExecutionStatus("GO 2");
			}
		};
	}

	@Bean
	public Step step1() {
		return stepBuilderFactory.get("step1")
				.tasklet(new Tasklet() {
					@Override
					public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
						LOGGER.info("execute step1");
						throw new RuntimeException("mock");
					}
				})
				.allowStartIfComplete(true)
				.build();
	}

	@Bean
	public Step step2() {
		return stepBuilderFactory.get("step2")
				.tasklet(new Tasklet() {
					@Override
					public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
						LOGGER.info("execute step2");
						return RepeatStatus.FINISHED;
					}
				})
				.allowStartIfComplete(true)
				.build();
	}

	@Bean
	public Step step3() {
		return stepBuilderFactory.get("step3")
				.tasklet(new Tasklet() {
					@Override
					public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
						LOGGER.info("execute step3");
						return RepeatStatus.FINISHED;
					}
				})
				.allowStartIfComplete(true)
				.build();
	}

}
